home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 05.zip / BS1 part 5 / SASC_6.0_Disk_7.adf / Source_And_Examples / source / c.a < prev    next >
Encoding:
Text File  |  1992-07-30  |  40.4 KB  |  1,139 lines

  1. *
  2. * C initial startup procedure under AmigaDOS
  3. * Use the following command line to make c.o
  4. * asm -u -isc:Assembler_Include/ c.a
  5. *
  6. * Use the following command line to make cres.o
  7. * asm -u -isc:Assembler_Include/ -dRESIDENT -ocres.o c.a
  8. *
  9. * Use the following command line to make catch.o (standard GURU catcher)
  10. * asm -u -isc:Assembler_Include/ -dCATCH -ocatch.o c.a
  11. *
  12. * Use the following command line to make catchnr.o (GURU catcher w/out requester)
  13. * asm -u -isc:Assembler_Include/ -dCATCH -dNOREQ -ocatchnr.o c.a
  14. *
  15. * Use the following command line to make catchres.o (resident GURU catcher)
  16. * asm -u -isc:Assembler_Include/ -dCATCH -dRESIDENT -ocatchres.o c.a
  17. *
  18. * Use the following command line to make catchresnr.o (resi GURU catcher w/out req)
  19. * asm -u -isc:Assembler_Include/ -dCATCH -dRESIDENT -dNOREQ -ocatchresnr.o c.a
  20. *
  21.         IFD  CATCH
  22.           IFND NOREQ
  23. AUTOREQ         set        1
  24.           ENDC
  25.         ENDC
  26.  
  27.         INCLUDE        "exec/types.i"
  28.         INCLUDE        "exec/alerts.i"
  29.         INCLUDE        "exec/nodes.i"
  30.         INCLUDE        "exec/lists.i"
  31.         INCLUDE        "exec/ports.i"
  32.         INCLUDE        "exec/libraries.i"
  33.         INCLUDE        "exec/tasks.i"
  34.         INCLUDE        "exec/memory.i"
  35.         INCLUDE        "exec/execbase.i"
  36.         INCLUDE        "libraries/dos.i"
  37.         INCLUDE        "libraries/dosextens.i"
  38.         INCLUDE        "workbench/startup.i"
  39.         INCLUDE        "exec/funcdef.i"
  40.         INCLUDE        "exec/exec_lib.i"
  41.         INCLUDE        "libraries/dos_lib.i"
  42.  
  43.         IFD   CATCH
  44.         INCLUDE        "intuition/intuition.i"
  45. VERSION  equ    1
  46. REVISION equ    0
  47.         ENDC
  48.         
  49. MEMFLAGS        EQU        MEMF_CLEAR+MEMF_PUBLIC
  50. AbsExecBase     EQU        4
  51.  
  52. ;;;
  53. ;;;   Stack map.
  54. ;;;
  55.       OFFSET  0
  56.            ds.b    4
  57. savereg    ds.b    13*4
  58. stackbtm   ds.b    4
  59.  
  60.  
  61.  
  62. ; some usefull macros:
  63.  
  64. callsys macro
  65.         CALLLIB _LVO\1
  66.         endm
  67.         
  68.         xdef        _XCEXIT                * exit(code) is standard way to leave C.
  69.         xdef        @_XCEXIT
  70.         
  71.         xref        LinkerDB        * linker defined base value
  72.         xref        _BSSBAS                * linker defined base of BSS
  73.         xref        _BSSLEN                * linker defined length of BSS
  74.         xref        __stack
  75.  
  76.        IFD          RESIDENT
  77.         xref        RESLEN
  78.         xref        RESBASE
  79.         xref        NEWDATAL
  80.        ENDC
  81.         
  82. *       library references
  83.  
  84.         section text,code
  85.  
  86.         xref    __main                  * Name of C program to start with.
  87.         xref    _MemCleanup             * Free all allocated memory
  88.         xref    __fpinit                * initialize floating point
  89.         xref    __fpterm                * terminate floating point
  90.  
  91. start:
  92.         movem.l d1-d6/a0-a6,-(a7)       * save registers
  93.  
  94.         move.l  a0,a2                   * save command pointer
  95.         move.l  d0,d2                   * and command length
  96.         lea     LinkerDB,a4             * load base register
  97.         move.l  AbsExecBase.W,a6
  98.  
  99.  
  100.         IFND        RESIDENT
  101.         lea     _BSSBAS,a3              * get base of BSS
  102.         moveq   #0,d1
  103.         move.l  #_BSSLEN,d0             * get length of BSS in longwords
  104.         bra.s   clr_lp                  * and clear for length given
  105. clr_bss move.l  d1,(a3)+
  106. clr_lp  dbf     d0,clr_bss
  107.         move.l  a7,_StackPtr(A4)        * Save stack ptr
  108.         move.l  a6,SysBase(A4)
  109.  
  110. *------ get the size of the stack, if CLI use cli_DefaultStack
  111. *------                                 if WB use a7 - TC_SPLOWER
  112.         move.l        ThisTask(a6),A3
  113.         move.l        pr_CLI(A3),d0
  114.         beq.s         fromwb
  115.         lsl.l         #2,d0
  116.         move.l        d0,a0
  117.         move.l        cli_DefaultStack(a0),d0
  118.         lsl.l         #2,d0             * # longwords -> # bytes
  119.         bra.s         dostack
  120.  
  121. fromwb:
  122.         move.l        a7,d0                         
  123.         sub.l         TC_SPLOWER(a3),d0
  124. dostack:
  125.  
  126. *------ Set __base for stack checking
  127.         move.l       a7,d1
  128.         sub.l        d0,d1               * get top of stack
  129.         add.l        #128,D1             * allow for parms overflow
  130.         move.l       D1,__base(A4)       * save for stack checking
  131.         
  132.         cmp.l         __stack(a4),d0
  133.         bcc.s        nochange        
  134.  
  135. *-- current stack is not as big as __stack says it needs
  136. *-- to be. Allocate a new one.
  137.         move.l        __stack(a4),d0
  138.         add.l         #128,d0           * extra room
  139.         move.l        d0,newstacksize(a4)
  140.  
  141.         move.l        #MEMFLAGS,d1
  142.         callsys       AllocMem
  143.         tst.l         d0
  144.         beq.w         return
  145.         
  146.         move.l        d0,newstack(a4)
  147.         add.l         #128,d0           * extra room
  148.         move.l        d0,__base(a4)
  149.         
  150.         add.l         __stack(a4),d0
  151.         move.l        d0,a7
  152.                 
  153. nochange:
  154.         ENDC
  155.  
  156.  
  157.  
  158.         IFD        RESIDENT
  159.         move.l        d2,-(a7)
  160.         movem.l       a0-a2,-(a7)
  161.  
  162. *------ get the size of the stack, if CLI use cli_DefaultStack
  163. *------                                 if WB use a7 - TC_SPLOWER
  164.         move.l        ThisTask(a6),A3
  165.         move.l        pr_CLI(A3),d1
  166.         beq.s         fromwb
  167.         lsl.l         #2,d1
  168.         move.l        d1,a0
  169.         move.l        cli_DefaultStack(a0),d1
  170.         lsl.l         #2,d1             * # longwords -> # bytes
  171.         bra.s         dostack
  172.  
  173. fromwb:
  174.         move.l        a7,d1                         
  175.         sub.l         TC_SPLOWER(a3),d1
  176. dostack:
  177.         moveq        #0,d2              * use d2 as flag for newstack or not
  178.         move.l       #RESLEN,d0
  179.         cmp.l        __stack(a4),d1     * This a4 is in the original 
  180.                                         * set of data
  181.         bcc.s        nochange        
  182.         move.l        __stack(a4),d1
  183.         add.l        d1,d0              * increase size of mem for new stack
  184.         moveq        #1,d2              * set flag
  185.                 
  186. nochange:
  187.         move.l        d1,a3             * save stacksize to set up stack checking
  188.         move.l        #MEMFLAGS,d1
  189.         callsys       AllocMem
  190.         tst.l         d0
  191.         bne.s         ok1
  192.         movem.l       (a7)+,d2/a0-a2
  193.         bra.w         return
  194.  
  195. ok1:    move.l        d0,a0
  196.         move.l        d0,a2             * a2 now has difference
  197.         
  198.         move.l        d0,a1
  199.         move.l        #NEWDATAL,d0
  200.         sub.l         #RESBASE,a4
  201.  
  202.                                         * copy data over
  203. cpy:    move.l        (a4)+,(a0)+
  204.         subq.l        #1,d0
  205.         bne.s         cpy
  206.  
  207.                                         * a4 now points at number of relocs
  208.         move.l        (a4)+,d0
  209. reloc:  beq.s         nreloc
  210.         move.l        a1,a0
  211.         add.l         (a4)+,a0          * a0 now has add of reloc
  212.         add.l         (a0),a2
  213.         move.l        a2,(a0) 
  214.         move.l        a1,a2             * restore offset
  215.         subq.l        #1,d0
  216.         bra.s         reloc
  217.         
  218. nreloc: move.l        a1,a4             * set up new base register
  219.         add.l         #RESBASE,a4
  220.  
  221.         move.l        #RESLEN,realdatasize(a4)
  222.         movem.l       (a7)+,a0-a2
  223.  
  224.         move.l        a6,SysBase(A4)
  225.         tst.b         d2
  226.         movem.l       (a7)+,d2          * restore d2 
  227.         movem.l       a7,_StackPtr(A4)  * Save stack ptr (movem doesn't
  228.                                         * change flags
  229.         beq.s         nochg2
  230.  
  231. *------ set up new stack
  232.         move.l       a4,d0
  233.         sub.l        #RESBASE,d0
  234.         add.l        #RESLEN,d0
  235.         add.l        __stack(a4),d0     * here a4 will be pointing at the
  236.                                         * new data, but __stack will be the
  237.                                         * same if all goes well
  238.         sub.l        #128,d0            * 128 down for good measure
  239.         move.l       d0,a7
  240.         move.l       __stack(a4),d0
  241.         move.l       d0,4(a7)            * fill in size of new stack        
  242.         add.l        d0,realdatasize(a4) * need to know how much to free later
  243.  
  244. nochg2:
  245. *------ Set __base for stack checking
  246.         move.l       a7,d1
  247.         sub.l        a3,d1               * get top of stack
  248.         add.l        #128,D1             * allow for parms overflow
  249.         move.l       D1,__base(A4)       * save for stack checking
  250.  
  251.         ENDC
  252.  
  253.  
  254.  
  255.         ifd     CATCH
  256.         move.w  AttnFlags(a6),Environment+2(a4) * save copy for dump
  257.         endc
  258.  
  259.  
  260.  
  261. clrwb:
  262.         clr.l        _WBenchMsg(A4)
  263.  
  264. *-----  clear any pending signals
  265.         moveq         #0,d0
  266.         move.l        #$00003000,d1
  267.         callsys       SetSignal
  268.         
  269.  
  270.         move.l        ThisTask(a6),A3
  271.  
  272.         ifd        CATCH
  273.         move.l        A3,TaskID(a4)
  274.  
  275. *------ initialize exception handler
  276. *------ Remember to preserve the old handler first
  277.         move.l        TC_TRAPDATA(a3),oldtrapdata(A4)
  278.         move.l        TC_TRAPCODE(a3),d0              ; check current exception
  279.         move.l        d0,oldtrapcode(A4)
  280.  
  281.         move.l        d0,a1
  282.         callsys TypeOfMem
  283.         tst.l d0
  284.         bne.s        1$                               * somebody else (debugger?) has vector
  285.  
  286.         move.l        #Exception,TC_TRAPCODE(a3)      * install pointers to code
  287.         move.l        a4,TC_TRAPDATA(a3)              * ...and data
  288. 1$:
  289.         ifd         AUTOREQ
  290. *------ attempt to open Intuition library:
  291.         bsr.w                openIntui
  292.         endc
  293.         endc
  294.  
  295.  
  296. *------ attempt to open DOS library:
  297.         lea           DOSName(PC),A1
  298.         moveq.l       #0,D0
  299.         callsys       OpenLibrary
  300.         move.l        D0,DOSBase(A4)
  301.         bne.s         ok2
  302.         moveq.l       #100,d0
  303.         bra.w         exit2
  304.  
  305. ok2:
  306.  
  307. *------ are we running as a son of Workbench?
  308.         move.l        pr_CurrentDir(A3),__curdir(A4)
  309.         tst.l         pr_CLI(A3)
  310.         beq.w         fromWorkbench
  311.         
  312. *=======================================================================
  313. *====== CLI Startup Code ===============================================
  314. *=======================================================================
  315. *
  316. * Entry: D2 = command length
  317. *        A2 = Command pointer
  318. fromCLI:
  319.         ifd        CATCH
  320.         moveq         #-1,d0
  321.         move.l        d0,Starter(a4)        * non-zero means CLI
  322.         move.l        a5,StackTop(a4)
  323.         endc
  324.  
  325. *------ find command name:
  326.         move.l      pr_CLI(a3),a0
  327.         add.l       a0,a0                   * bcpl pointer conversion
  328.         add.l       a0,a0
  329.         move.l      cli_CommandName(a0),a1
  330.  
  331.         IFD         CATCH 
  332.         IFND        AUTOREQ
  333.         move.l      cli_StandardOutput(a0),GConsole(a4)   * save output fh
  334.         ENDC
  335.         ENDC
  336.         
  337.         add.l       a1,a1                   * bcpl pointer conversion
  338.         add.l       a1,a1
  339.  
  340. *------ collect parameters:
  341.         move.l      d2,d0                   * get command line length
  342.         moveq.l     #0,d1
  343.         move.b      (a1)+,d1
  344.         move.l      a1,_ProgramName(A4)
  345.         add.l       d1,d0                   * add length of command name
  346.         addq.l      #7,d0                   * allow for space after command, quotes
  347.                                             * and null terminator, as well as 
  348.         andi.w      #$fffc,D0               * force to long word boundary
  349.         move.l      d0,Commandlen(a4)
  350.    
  351.         movem.l     d1/a1,-(a7)
  352.         move.l      #MEMFLAGS,d1
  353.         callsys     AllocMem
  354.         movem.l     (a7)+,d1/a1
  355.         tst.l       d0
  356.         bne.s       ok_copy
  357.    
  358.         move.l      #1000,d0                * what should the return code be for out of mem?
  359.         move.l      d0,-(a7)                * put a return code on the stack
  360.         beq.w       nodofree                * Was exitToDOS
  361.    
  362. ok_copy:
  363.         move.l      d0,a0
  364.         move.l      d0,Commandbuf(a4)
  365.          
  366. *------ copy command line into memory
  367.         move.l     d2,d0                    * get command line length
  368.         subq.l     #1,d0
  369.         add.l      d1,d2
  370.    
  371. copy_line:
  372.         move.b     0(A2,D0.W),2(A0,D2.W)    * copy command line to stack
  373.         subq.l     #1,d2
  374.         dbf        d0,copy_line
  375.         move.b     #' ',2(a0,d2.w)          * add space between command and parms
  376.         subq.l     #1,d2
  377.         move.b     #'"',2(a0,d2.w)          * add end quote
  378.    
  379. copy_cmd:
  380.         move.b     0(a1,d2.w),1(a0,d2.w)    * copy command name to stack
  381.         dbf        d2,copy_cmd
  382.         move.b     #'"',(a0)
  383.         move.l     A0,-(A7)                 * push command line address
  384.         bra.s      main                     * call C entrypoint
  385.  
  386. *=======================================================================
  387. *====== Workbench Startup Code =========================================
  388. *=======================================================================
  389.  
  390. fromWorkbench:
  391.  
  392.         ifd        CATCH
  393.         move.l     TC_SPUPPER(a3),StackTop(a4)  * set top of stack
  394.         endc
  395.  
  396.  
  397. *------ we are now set up.  wait for a message from our starter
  398.         lea        pr_MsgPort(A3),a0         * our process base
  399.         callsys    WaitPort
  400.         lea        pr_MsgPort(A3),a0         * our process base
  401.         callsys    GetMsg
  402.         move.l     d0,_WBenchMsg(a4)
  403.         move.l     d0,-(SP)
  404.  
  405.         move.l     d0,a2                     * get first argument
  406.         move.l     sm_ArgList(a2),d0
  407.         beq.s      do_main
  408.         move.l     DOSBase(a4),a6
  409.         move.l     d0,a0
  410.         move.l     wa_Lock(a0),d1
  411.         callsys    DupLock
  412.         move.l     d0,__curdir(A4)
  413.         move.l     d0,d1
  414.         callsys    CurrentDir
  415.  
  416. do_main:
  417.         move.l     _WBenchMsg(A4),a0         * get address of workbench message
  418.         move.l     a0,-(a7)                  * push argv
  419.         pea        NULL(a4)                  * push argc
  420.         move.l     sm_ArgList(a0),a0         * get address of arguments
  421.         move.l     wa_Name(a0),_ProgramName(A4) * get name of program
  422.  
  423. *=============================================
  424. *------ common code --------
  425. *=============================================
  426.  
  427. main    jsr        __fpinit(PC)              * Initialize floating point
  428.         jsr        __main(PC)                * call C entrypoint
  429.         moveq.l    #0,d0                     * set successful status
  430.         bra.s      exit2
  431. *
  432.  
  433. XCEXIT:
  434. _XCEXIT:
  435.         move.l     4(SP),d0                  * extract return code
  436. @XCEXIT:
  437. @_XCEXIT:
  438. exit2:
  439.         movea.l    _StackPtr(a4),a7          * restore stack ptr
  440.         move.l     d0,-(a7)
  441.         move.l     _ONEXIT(A4),d0            * exit trap function?
  442.         beq.s      exit3
  443.         move.l     d0,a0
  444.         jsr        (a0)
  445. exit3:
  446.         jsr        __fpterm(PC)              * clean up any floating point
  447.         jsr        _MemCleanup(PC)           * cleanup leftover memory alloc.
  448.  
  449.         ifnd       RESIDENT
  450. *------ free the stack if we allocated one
  451.         move.l     newstacksize(a4),d0
  452.         beq.s      exit4
  453.         move.l     newstack(a4),a1
  454.         move.l     AbsExecBase.W,A6
  455.         callsys    FreeMem
  456.         endc
  457.  
  458. exit4:
  459. *------ if we ran from CLI, skip workbench cleanup:
  460.         tst.l      _WBenchMsg(A4)
  461.         beq.s      exitToDOS
  462.         move.l     DOSBase(A4),a6
  463.         move.l     __curdir(a4),d1
  464.         beq.s      done_5
  465.         callsys    UnLock
  466. done_5:
  467. *------ return the startup message to our parent
  468. *       we forbid so workbench can't UnLoadSeg() us
  469. *       before we are done:
  470.         move.l     AbsExecBase.W,A6
  471.         callsys    Forbid
  472.         move.l     _WBenchMsg(a4),a1
  473.         callsys    ReplyMsg
  474.         bra.s      nodofree
  475.  
  476. exitToDOS:
  477.         move.l     AbsExecBase.W,a6
  478.  
  479. *------ Restore the original exception handler
  480.         ifd    CATCH
  481.         move.l        ThisTask(a6),A3
  482.         move.l        oldtrapdata(A4),TC_TRAPDATA(a3)
  483.         move.l        oldtrapcode(A4),TC_TRAPCODE(a3) * check current exception
  484.          ifd         AUTOREQ
  485.           move.l        IntuiBase(a4),a1
  486.           callsys         CloseLibrary                * close Intuition library
  487.          endc
  488.         ENDC
  489.  
  490. *------ free the command line buffer
  491.         move.l     Commandlen(a4),d0
  492.         beq.s      nodofree
  493.         move.l     Commandbuf(a4),a1
  494.         callsys    FreeMem
  495.    
  496. *------ this rts sends us back to DOS:
  497. nodofree:
  498.         move.l     DOSBase(A4),a1
  499.         callsys    CloseLibrary              * close Dos library
  500.  
  501.         IFD        RESIDENT
  502.         move.l     realdatasize(a4),d0
  503.         move.l     a4,a1
  504.         sub.l      #RESBASE,a1
  505.         callsys    FreeMem
  506.         ENDC
  507.         move.l     (a7)+,d0
  508.  
  509. return:        
  510.         movem.l    (a7)+,d1-d6/a0-a6
  511.         rts
  512.  
  513. DOSName dc.b    'dos.library',0
  514.  
  515.         ifd        CATCH
  516. *-----------------------------------------------------------------------
  517. *        Open the Intuition library:
  518.  
  519. openIntui:
  520.         lea        IntuiName(PC),A1
  521.         moveq.l    #0,D0
  522.         callsys    OpenLibrary
  523.         move.l     D0,IntuiBase(A4)
  524.         beq.s      noDOS
  525.         rts
  526.  
  527. *-----------------------------------------------------------------------
  528. noDOS:
  529.         moveq.l #100,d0
  530.         bra.w    exit2
  531.  
  532.  
  533. IntuiName  dc.b        'intuition.library',0
  534.  
  535. *-----------------------------------------------------------------------
  536. *        The Exception Handler - catches GURUs and exits (semi)cleanly
  537. Exception:
  538.         movem.l    a0,-(a7)
  539.         move.l     AbsExecBase.W,a0
  540.         move.l     ThisTask(a0),a0
  541.         move.l     TC_TRAPDATA(a0),a0        * ...and data
  542.         move.l     (sp)+,ADump(a0)           * save a0
  543.         move.l     d0,ADump+4(a0)            * and d0
  544.  
  545.         move.l     (a7)+,d0                  * get exception # from stack
  546.         move.l     d0,GURUNum(a0)            * and save it
  547.         cmpi.l     #3,d0                     * ADDRESS or BUS error?
  548.         bgt.s      1$                        * no, skip adjustment
  549.         btst       #0,Environment+3(a0)      * is it 68010 or 68020?
  550.         bne.s      1$                        * 0 means NO
  551.         addq.l     #8,a7                     * adjust for 68000
  552. 1$:
  553.         move.l     2(a7),d0                  * get PC at crash
  554.         move.l     d0,GURUAddr(a0)           * and save it
  555.         move.l     ADump+4(a0),d0            * restore a0 and d0
  556.         move.l     ADump(a0),a0
  557.         move.l     #GURUExit,2(a7)           * use our own exit point
  558.         rte
  559.         
  560. *-----------------------------------------------------------------------
  561. *        The Exception exit routine - write 'PGTB' IFF chunk to file
  562. *        'SnapShot.TB' in current directory, then exit to system.
  563.  
  564. GURUExit:
  565.         movem.l    d0-d7/a0-a7,-(sp)         * save all registers
  566.         move.l     AbsExecBase.W,a6          * make sure we are working with Exec
  567.         callsys    GetCC                     * safe way - works with all CPUs
  568.         move.l     ThisTask(a6),a3
  569.         move.l     TC_TRAPDATA(a3),a4        * make sure we have a valid # in a4
  570.         move.l     d0,Flags(a4)              * save area
  571.         movem.l    (sp)+,d0-d7
  572.         movem.l    d0-d7,DDump(a4)           * save data reg contents
  573.         movem.l    (sp)+,d0-d7
  574.         movem.l    d0-d7,ADump(a4)           * save address reg contents
  575.         tst.l      StackPtr(a4)              * if there's something there
  576.         bne        GExit1                    * ...we've been here before!
  577.         lea        TempStore(a4),a0          * calculate addr of TempStore
  578.         move.l     a0,TempAddr(a4)           * ...and save for later access
  579.         move.l     A7Store(a4),d0            * make sure we have proper TOS
  580.         move.l     d0,StackPtr(a4)           * ...and save it
  581.         moveq      #0,d0
  582.         move.l     _ProgramName(a4),a0       * find length of program name
  583.  
  584.         ifd        AUTOREQ
  585.         move.l     a0,PName(a4)
  586.         endc
  587.  
  588.         subq.l     #1,a0
  589.         move.b     (a0),d0
  590.         addq.l     #4,d0                     * adjust for shift
  591.         lsr.l      #2,d0
  592.         move.l     d0,NameLen(a4)            * store length
  593.         add.l      d0,FAILlen(a4)            * and sub-chunk total
  594.  
  595.         moveq      #0,d0                     * clear d0 for use
  596.         lea        VBlankFrequency(a6),a0    * set up a0 to find correct data
  597.         move.b     (a0)+,d0                  * get just in case
  598.         move.l     d0,VBlankFreq(a4)         * ...so we can figure what
  599.         move.b     (a0),d0                   * ...type of machine
  600.         move.l     d0,PowerSupFreq(a4)       * ...we're working on
  601.  
  602.         lea        start-4(pc),a0            * get seglist ptr
  603.         moveq      #-1,d0                    * always at least 1
  604. 2$:
  605.         addq.l     #1,d0
  606.         move.l     (a0),d1                   * find end of list
  607.         beq.s      3$
  608.         lsl.l      #2,d1                     * BPTR!!!!!
  609.         move.l     d1,a0
  610.         bra.s      2$
  611. 3$:
  612.         add.l      d0,SegCount(a4)           * store # of seglist pointers
  613.         lsl.l      #1,d0                     * multiply by 2 for longword count
  614.         add.l      d0,FAILlen(a4)            * and sub-chunk length
  615.  
  616.         move.l     StackTop(a4),d0           * get top of stack
  617.         sub.l      StackPtr(a4),d0           * find number of bytes used
  618.         addq.l     #4,d0                     * adjust for longword conversion
  619.         lsr.l      #2,d0                     * convert from bytes to long
  620.         move.l     d0,StackLen(a4)           * and save
  621.         add.l      d0,s2len(a4)              * and sub-chunk total
  622.  
  623.         move.l     a5,-(sp)                  * save a5 for later
  624.         callsys    Forbid                    * don't let 'em change while we ask
  625.         move.l     MemList+LH_HEAD(a6),d0    * first node in MemList
  626. checkchip:
  627.         move.l     d0,a5                     * move node address to address reg
  628.         move.w     MH_ATTRIBUTES(a5),d4      * get node attributes
  629.         btst       #MEMB_CHIP,d4             * is it chip?
  630.         beq.s      checkfast                 * no, go on
  631.         lea        chipAvail(a4),a3
  632.         bsr.w      AddIt
  633. checkfast:
  634.         btst       #MEMB_FAST,d4             * is it fast?
  635.         beq.s      next                      * no, go on
  636.         lea        fastAvail(a4),a3
  637.         bsr.w      AddIt
  638. next:
  639.         move.l     LN_SUCC(a5),d0            * get address of next node
  640.         bne.s      checkchip                 * ...and loop back if valid
  641.         callsys    Permit                    * allow others access again
  642.         move.l     #MEMF_CHIP+MEMF_LARGEST,d1 * to find largest hunk in chip ram
  643.         callsys    AvailMem
  644.         move.l     d0,chipLargest(a4)         * store
  645.         move.l     #MEMF_FAST+MEMF_LARGEST,d1 * to find largest hunk in fast ram
  646.         callsys    AvailMem
  647.         move.l     d0,fastLargest(a4)        * store
  648.         move.l     (sp)+,a5                  * and restore a5
  649.  
  650.         ifd        AUTOREQ
  651.         moveq      #0,d0                     * PosFlag
  652.         move.l     d0,d1                     * NegFlag
  653.         move.l     d0,a0                     * 0 means use current window
  654.         lea        IText1(a4),a1             * Body Text
  655.         lea        IText5(a4),a2             * Positive Gadget Text
  656.         lea        IText6(a4),a3             * Negative Gadget Text
  657.         moveq      #1,d2
  658.         lsl.l      #8,d2                     * quick way to set Width
  659.         moveq      #76,d3                    * Height
  660.         move.l     IntuiBase(a4),a6          * get intuition library pointer
  661.         jsr        -$15c(A6)                 * callsys       AutoRequest
  662.         move.l     AbsExecBase.W,a6
  663.         tst.l      d0                        * save SnapShot?
  664.         beq.w      GExit2                    * no, just exit
  665.         endc
  666.  
  667.         move.l     DOSBase(a4),a6
  668.         lea        DumpName(a4),a0           * get name of output file
  669.         move.l     a0,d1
  670.         move.l     #MODE_NEWFILE,d2          * create new file
  671.         callsys    Open 
  672.         bne.s      4$
  673.         lea        DumpPath(a4),a0           * if error in current dir, try DF1:
  674.         move.l     a0,d1
  675.         move.l     #MODE_NEWFILE,d2
  676.         callsys    Open
  677.         bne.s      4$
  678.         move.b     #'0',DumpPath+2(a4)       * still error?  Try DF0:
  679.         lea        DumpPath(a4),a0
  680.         move.l     a0,d1
  681.         move.l     #MODE_NEWFILE,d2
  682.         callsys    Open
  683.  
  684.         ifnd        AUTOREQ
  685.         bne.s      4$                        * if no error, continue (finally!)
  686.         move.l     GConsole(a4),d1
  687.         beq.w      GExit2
  688.         lea        failmsg(a4),a0
  689.         move.l     a0,d2
  690.         move.l     #23,d3
  691.         callsys    Write
  692.         endc
  693.  
  694.         bra.w      GExit2                    * else, print msg & DIE gracefully
  695. 4$:
  696.         move.l     d0,d5                     * save file handle for Write
  697.         move.l     d0,fp(a4)                 * ...and in a safe place for later
  698.         move.l     d5,d1                     * get file handle
  699.         lea        PGTB(a4),a0               * first part of fixed
  700.         move.l     a0,d2
  701.         move.l     #chunk_len_1,d3           * length of first
  702.         callsys    Write                     * ...since it gets written over
  703.  
  704.         move.l     d5,d1                     * get file handle
  705.         move.l     _ProgramName(a4),d2       * get address of program name
  706.         move.l     NameLen(a4),d3            * get # longs in program name
  707.         lsl.l      #2,d3                     * ..and convert to bytes
  708.         callsys    Write
  709.  
  710.         move.l     d5,d1                     * get file handle
  711.         lea        Environment(a4),a0        * second part of fixed
  712.         move.l     a0,d2
  713.         move.l     #chunk_len_2,d3           * length of second part
  714.         callsys    Write
  715.  
  716.         lea        start-8(pc),a0            * address of seglist (size of seg)
  717.         move.l     (a0)+,d0                  * segsize
  718.         move.l     d0,TempStore+4(a4)        * save it
  719.         move.l     a0,TempStore(a4)          * store first number
  720.         move.l     SegCount(a4),d4
  721. 5$:
  722.         move.l     d5,d1                     * get file handle
  723.         move.l     TempAddr(a4),d2           * address of write buffer
  724.         moveq      #TempSize,d3              * size of segment pointer
  725.         callsys    Write
  726.         move.l     TempStore(a4),a0          * retrieve pointer
  727.         move.l     (a0),d0                   * get next seg pointer
  728.         lsl.l      #2,d0                     * adjust
  729.         move.l     d0,TempStore(a4)          * ..and save
  730.         move.l     d0,a0
  731.         beq.b      donesegs                  * last segment?
  732.         move.l     -4(a0),d0                 * get segsize
  733.         move.l     d0,TempStore+4(a4)        * ...and save it
  734.         subq.l     #1,d4                     * done yet?
  735.         bne.s      5$                        * no, do next
  736.  
  737. donesegs:
  738.         tst.l      _FMEM(a4)                 * do they want memory reported?
  739.         beq.s      55$                       * no, forget it
  740.         move.l     d5,d1
  741.         lea        subFMEM(a4),a0
  742.         move.l     a0,d2
  743.         move.l     #FMEMlen,d3
  744.         callsys    Write
  745.  
  746. 55$:
  747.         move.l     d5,d1                     * (get the idea?)
  748.         lea        subREGS(a4),a0            * third part of fixed
  749.         move.l     a0,d2
  750.         move.l     #chunk_len_3,d3           * length of third
  751.         callsys    Write
  752.  
  753.         move.l     StackLen(a4),d0           * get length of stack used
  754.         cmpi.l     #2048,d0                  * > 8k ?
  755.         bgt.s      6$                        * yes, dump two chunks
  756.         move.l     d5,d1
  757.         lea        STAK2(a4),a0              * whole stack chunk
  758.         move.l     a0,d2
  759.         moveq      #STAK2len,d3              * length of fixed part
  760.         callsys    Write
  761.  
  762.         move.l     d5,d1
  763.         move.l     StackPtr(a4),d2           * address of stack
  764.         move.l     StackLen(a4),d3           * get # longwords on stack
  765.         lsl.l      #2,d3                     * ..and convert to bytes
  766.         callsys    Write
  767.         bra.s      7$
  768. 6$:
  769.         move.l     d5,d1
  770.         lea        STAK3(a4),a0              * top4k chunk
  771.         move.l     a0,d2
  772.         moveq      #STAK3len,d3              * length of fixed part
  773.         callsys    Write
  774.  
  775.         move.l     d5,d1
  776.         move.l     StackTop(a4),d2           * find top of stack
  777.         sub.l      #4096,d2                  * find top-4k
  778.         move.l     #4096,d3                  * # bytes to write
  779.         callsys    Write
  780.  
  781.         move.l     d5,d1
  782.         lea        STAK4(a4),a0              * bottom4k chunk
  783.         move.l     a0,d2
  784.         moveq      #STAK4len,d3              * length of fixed part
  785.         callsys    Write
  786.  
  787.         move.l     d5,d1
  788.         move.l     StackPtr(a4),d2           * current stack address
  789.         move.l     #4096,d3                  * # bytes to write
  790.         callsys    Write
  791. 7$:
  792.         move.l     _STAKOffset(a4),d3
  793.         beq.s      8$
  794.         lsr.l      #2,d3
  795.         addq.l     #1,d3
  796.         move.l     d3,_STAKOffset(a4)
  797.         addq.l     #1,d3
  798.         move.l     d5,d1
  799.         lea        STAK5(a4),a0
  800.         move.l     a0,d2
  801.         moveq      #STAK5len,d3
  802.         callsys    Write
  803.  
  804.         move.l     d5,d1
  805.         move.l     StackPtr(a4),d2
  806.         move.l     _STAKOffset(a4),d3
  807.         subq.l     #1,d3
  808.         move.l     StackLen(a4),d4
  809.         cmp.l      d3,d4
  810.         bge.s      75$
  811.         move.l     StackLen(a4),d3
  812. 75$:
  813.         lsl.l      #2,d3
  814.         callsys    Write
  815. 8$:
  816.         tst.l      _ONGURU(A4)               * user GURU function?
  817.         beq.s      9$
  818.         move.l     d5,-(sp)
  819.         move.l     d5,d1
  820.         lea        UDAT(a4),a0
  821.         move.l     a0,d2
  822.         move.l     #UDATlen,d3
  823.         callsys    Write
  824.         move.l     d5,d1
  825.         moveq      #0,d2                     * zero offset
  826.         moveq      #1,d3                     * ...from EOF
  827.         callsys    Seek
  828.         move.l     d0,SeekStore(a4)
  829.         move.l     _ONGURU(a4),a0
  830.         jsr        (a0)
  831.         addq.l     #4,sp
  832. 9$:
  833.         move.l     fp(a4),d5
  834.         move.l     d5,d1
  835.         moveq      #0,d2                     * offset from EOF
  836.         moveq      #1,d3                     * OFFSET_END
  837.         callsys    Seek                      * Seek returns OLD position
  838.         move.l     d0,d1
  839.         andi.l     #3,d1                     * did user write even longwords?
  840.         beq.s      10$                       * Yep!        Nice Human.
  841.         move.l     d1,d6                     * Nope, save for later.
  842.         clr.l      TempStore(a4)             * clear temp storage
  843.         move.l     d5,d1
  844.         move.l     TempAddr(a4),d2
  845.         moveq      #4,d3
  846.         sub.l      d6,d3                     * find how many NULLs to pad
  847.         callsys    Write
  848.         bra.s      9$
  849. 10$:
  850.         tst.l      SeekStore(a4)             * did we write UDAT?
  851.         beq.s      11$                       * nope!
  852.         sub.l      SeekStore(a4),d0          * find length of UDAT section
  853.         lsr.l      #2,d0                     * adjust to longwords
  854.         move.l     d0,TempStore(a4)          * save UDAT length for write
  855.         move.l     d5,d1
  856.         move.l     SeekStore(a4),d2          * find where to write it
  857.         subq.l     #4,d2
  858.         moveq      #-1,d3                    * OFFSET_BEGINNING
  859.         callsys    Seek
  860.         move.l     d5,d1
  861.         move.l     TempAddr(a4),d2
  862.         move.l     #4,d3
  863.         callsys    Write                     * write length of UDAT field to file
  864. 11$:
  865.         move.l     d5,d1
  866.         moveq      #0,d2                     * offset to 'Length' field
  867.         moveq      #1,d3                     * OFFSET_END
  868.         callsys    Seek                      * make sure we are at end of file
  869.         move.l     d5,d1
  870.         moveq      #4,d2                     * offset to 'Length' field
  871.         moveq      #-1,d3                    * OFFSET_BEGINNING
  872.         callsys    Seek
  873.         subq.l     #8,d0                     * adjust total length
  874.         lsr.l      #2,d0                     * adjust to longwords
  875.         move.l     d0,TempStore(a4)          * save for write
  876.         move.l     d5,d1
  877.         move.l     TempAddr(a4),d2
  878.         move.l     #4,d3
  879.         callsys    Write                     * write 'Length' field
  880. GExit1:
  881.         move.l     fp(a4),d1
  882.         beq.s      GExit2
  883.         move.l     DOSBase(a4),a6
  884.         callsys    Close
  885.  
  886.         ifnd        AUTOREQ
  887.         move.l      GConsole(a4),d1
  888.         beq.s       GExit2
  889.         lea         success(a4),a0
  890.         move.l      a0,d2
  891.         move.l      #32,d3
  892.         callsys     Write
  893.         endc
  894.         
  895. GExit2:
  896.         move.l       TaskID(a4),a6
  897.         move.l       AbsExecBase.W,a6
  898.         moveq        #$47,d0
  899.         bra.w        exit2
  900.  
  901. *-----------------------------------------------------------------------
  902. * AddIt:        routine to add memory parts to variables
  903.  
  904. AddIt:
  905.         move.l       MH_FREE(a5),d0
  906.         add.l        d0,(a3)                 * add to available
  907.         move.l       MH_UPPER(a5),d0
  908.         sub.l        MH_LOWER(a5),d0
  909.         add.l        d0,4(a3)                * add to Max section
  910.         rts
  911.         endc
  912.  
  913.  
  914.         IFD     CATCH
  915.         section __MERGED,DATA
  916. _ONGURU        dc.l        0
  917. IntuiBase      dc.l        0
  918. TaskID         dc.l        0
  919. oldtrapcode    dc.l        0
  920. oldtrapdata    dc.l        0
  921.  
  922.         ifnd        AUTOREQ
  923. GConsole        dc.l        0
  924. failmsg         dc.b        7,'Can''t write SnapShot!',10
  925. success         dc.b        7,'GURU caught; SnapShot written!',10
  926.         endc
  927.  
  928.         cnop        0,4
  929. _FMEM           dc.l        0
  930. fp              dc.l        0                  * save SnapShot file pointer
  931. DumpPath        dc.b        'DF1:'
  932. DumpName        dc.b        'SnapShot.TB',0
  933. SeekStore       dc.l        0
  934. TempAddr        dc.l        0                  * Storage for &TempStore
  935. TempStore       dc.l        0,0                * Temporary storage for BPTR -> APTR
  936. TempSize        equ        *-TempStore
  937.  
  938.         cnop        0,4
  939.         ifd        AUTOREQ
  940. TAttr:                                         * Text attributes for font
  941.         dc.l        TName                      * name of font
  942.         dc.w        TOPAZ_EIGHTY               * font size
  943.         dc.b        FS_NORMAL                  * font style
  944.         dc.b        FPF_ROMFONT                * font preferences
  945. TName:
  946.         dc.b        'topaz.font',0
  947.         cnop        0,4
  948.  
  949. IText1:                                        * Text definitions for AutoReq call
  950.         dc.b        3,0,RP_JAM1,0              * front & back pens, drawmode and filler byte
  951.         dc.w        6,4                        * XY origin relative to container TopLeft
  952.         dc.l        TAttr                      * font pointer or NULL for default
  953.         dc.l        ITextText1                 * pointer to text
  954.         dc.l        IText2                     * next IntuiText structure
  955. ITextText1:
  956.         dc.b        'Program:',0
  957.         cnop 0,4
  958. IText2:
  959.         dc.b        3,0,RP_JAM1,0
  960.         dc.w        78,4
  961.         dc.l        TAttr
  962. PName   dc.l        0
  963.         dc.l        IText3
  964.         cnop        0,4
  965. IText3:
  966.         dc.b        3,0,RP_JAM1,0
  967.         dc.w        55,16
  968.         dc.l        TAttr
  969.         dc.l        ITextText3
  970.         dc.l        IText4
  971. ITextText3:
  972.         dc.b        'I caught a GURU!',0
  973.         cnop 0,4
  974. IText4:
  975.         dc.b        3,0,RP_JAM1,0
  976.         dc.w        20,28
  977.         dc.l        TAttr
  978.         dc.l        ITextText4
  979.         dc.l        0
  980. ITextText4:
  981.         dc.b        'Should I make a SnapShot?',0
  982.         cnop 0,4
  983. IText5:
  984.         dc.b        3,0,RP_JAM2,0
  985.         dc.w        6,3
  986.         dc.l        TAttr
  987.         dc.l        ITextText5
  988.         dc.l        0
  989. ITextText5:
  990.         dc.b        'YES',0
  991.         cnop 0,4
  992. IText6:
  993.         dc.b        3,0,RP_JAM2,0
  994.         dc.w        6,3
  995.         dc.l        TAttr
  996.         dc.l        ITextText6
  997.         dc.l        0
  998. ITextText6:
  999.         dc.b        'NO',0
  1000.         endc
  1001.  
  1002.         cnop 0,4
  1003.  
  1004. *--------------------------------------------------------------------------
  1005. * New IFF chunk format -
  1006. *        PGTB = Program Traceback, header for chunk
  1007. *        FAIL = reason for and environment of crash
  1008. *        REGS = registers at time of crash, including PC and CCR
  1009. *        VERS = version, revision, name of this program
  1010. *        STAK = ENTIRE stack at time of crash or, alternately,
  1011. *                the top and bottom 4k if the stack used is > 8k
  1012. *        UDAT = optional user data dump (if _ONGURU is set to a
  1013. *                function pointer in the user's program)
  1014. *--------------------------------------------------------------------------
  1015.  
  1016. PGTB            dc.b        'PGTB'
  1017. Length          dc.l        0                * length of chunk (in longwords)
  1018.  
  1019. subFAIL         dc.b        'FAIL'
  1020. FAILlen         dc.l        9
  1021. NameLen         dc.l        0                * length of program name
  1022. chunk_len_1     equ         *-PGTB
  1023. Environment     dc.l        0                * CPU (, Math)
  1024. VBlankFreq      dc.l        0                *        PAL = 50, NTSC = 60 (approx.)
  1025. PowerSupFreq    dc.l        0                * Europe = 50,        USA = 60 (approx.)
  1026. Starter         dc.l        0                * 0 = WB, -1 = CLI
  1027. GURUNum         dc.l        0                * cause of crash (GURU #)
  1028. SegCount        dc.l        1                * # hunks in seglist
  1029. chunk_len_2     equ         *-Environment
  1030.  
  1031. subFMEM         dc.b        'FMEM'           * FMEM - free memory at crash
  1032.                 dc.l        6
  1033. chipAvail       dc.l        0                * available chip memory
  1034. chipMax         dc.l        0                *        maximum chip memory
  1035. chipLargest     dc.l        0                *        largest chip memory
  1036. fastAvail       dc.l        0                * available fast memory
  1037. fastMax         dc.l        0                *        maximum fast memory
  1038. fastLargest     dc.l        0                *        largest fast memory
  1039. FMEMlen         equ         *-subFMEM
  1040.  
  1041. subREGS         dc.b        'REGS'           * REGS - register storage field
  1042. REGSlen         dc.l        18
  1043. GURUAddr        dc.l        0                * PC at time of crash
  1044. Flags           dc.l        0                * Condition Code Register (CCR)
  1045. DDump           dc.l        0,0,0,0,0,0,0,0  * data registers
  1046. ADump           dc.l        0,0,0,0,0,0,0    * address registers
  1047. A7Store         dc.l        0
  1048.  
  1049. subVERS         dc.b        'VERS'           * VERS - program version field
  1050.                 dc.l        6
  1051.                 dc.l        VERSION          * version #
  1052.                 dc.l        REVISION         * revision #
  1053.                 dc.l        3                * length of name of program
  1054.                 IFD        RESIDENT
  1055.                 dc.b        'catchres.o',0,0 * name
  1056.                 ENDC
  1057.                 IFND        RESIDENT
  1058.                 dc.b        'catch.o   ',0,0 * name
  1059.                 ENDC
  1060.  
  1061. subSTAK         dc.b        'STAK'           * STAK - stack field
  1062. STAKlen         dc.l        4
  1063. Type            dc.l        0                * 0 = Info
  1064. StackTop        dc.l        0                * top of stack pointer
  1065. StackPtr        dc.l        0                * current Stack Pointer
  1066. StackLen        dc.l        0                * # bytes used on stack
  1067. chunk_len_3     equ         *-subREGS
  1068.  
  1069. STAK2           dc.b        'STAK'
  1070. s2len           dc.l        1                * length of subtype
  1071.                 dc.l        1                * 1 = whole stack
  1072. STAK2len        equ         *-STAK2
  1073.  
  1074. STAK3           dc.b        'STAK'
  1075.                 dc.l        1025
  1076.                 dc.l        2                * 2 = top 4k of stack
  1077. STAK3len        equ         *-STAK3
  1078.  
  1079. STAK4           dc.b        'STAK'
  1080.                 dc.l        1025
  1081.                 dc.l        3                * 3 = bottom 4k of stack
  1082. STAK4len        equ         *-STAK4
  1083.  
  1084. STAK5           dc.b        'STAK'
  1085. _STAKOffset     dc.l        0
  1086.                 dc.l        4                * 4 = user defined amount
  1087. STAK5len        equ         *-STAK5
  1088.  
  1089. UDAT            dc.b        'UDAT'
  1090.                 dc.l        0
  1091. UDATlen         equ         *-UDAT
  1092.         endc
  1093.  
  1094.  
  1095.  
  1096.         section __MERGED,BSS
  1097.  
  1098.         xref    DOSBase
  1099.  
  1100.         xdef    NULL,SysBase,_WBenchMsg
  1101.         xdef    __curdir
  1102.         xdef    _OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
  1103.         xdef    _SIGINT
  1104.         xdef    _ProgramName,_StackPtr,__base
  1105.         ifd        CATCH
  1106.         xdef        _ONGURU,_FMEM,_STAKOffset
  1107.         endc
  1108.  
  1109.  
  1110.         
  1111. NULL         ds.b    4        
  1112. __base       ds.b    4                   * base of stack
  1113. _OSERR       ds.b    4
  1114. _FPERR       ds.b    4
  1115. _SIGFPE      ds.b    4
  1116. _SIGINT      ds.b    4
  1117. _ONERR       ds.b    4
  1118. _ONEXIT      ds.b    4
  1119. _ONBREAK     ds.b    4
  1120. __curdir     ds.b    4
  1121. SysBase      ds.b    4
  1122. _WBenchMsg   ds.b    4
  1123. _StackPtr    ds.b    4
  1124. _ProgramName ds.b    4
  1125. Commandbuf   ds.b    4
  1126. Commandlen   ds.b    4
  1127.  
  1128.         ifd        RESIDENT
  1129. realdatasize ds.b    4                   * size of memory allocated for data +
  1130.                                          * possible stack
  1131.         endc
  1132.         ifnd       RESIDENT
  1133. newstack     ds.b    4                   * pointer to new stack (if needed)
  1134. newstacksize ds.b    4                   * size of new stack
  1135.         endc
  1136.  
  1137.              END
  1138.